#include "guish.hpp"

FileReceiver::FileReceiver(RemoteHost *source, const RPCParams *params)
	:StreamReceiver(source, params)
{
	filename = params->getString("path");
	id = params->getInt("id");
	
	string partialFileName = filename+".filepart";
	file = fopen(partialFileName.c_str(), "w");
	
	if(!file) {
		char buf[512];
		sprintf(buf, "Failed to open file: %s.", strerror(errno));
		reportError(buf);
	}
}

FileReceiver::~FileReceiver()
{
	if(file) {
		fclose(file);
	}
}


void FileReceiver::recv(int len, const char *data)
{
	assert(file);
	if(file)
	{
		if(!fwrite(data, 1, len, file))
		{
			trace << "File upload failed: "<< strerror(errno) << "\n"; //DEBUG
			reportError(retprintf("Failed writing file: %s.", strerror(errno)));
			
			fclose(file);
			file = NULL;
		}
		//trace << "FileReceiver::recv("<<len<<")\n"; //DEBUG
	}
}

void FileReceiver::onClose()
{
	if(file)
	{
		trace << "FileReceiver::onClose()\n"; //DEBUG
		fclose(file);
		file = NULL;
	}
}

void FileReceiver::disconnected()
{
	// TODO
}

void FileReceiver::finished()
{
	onClose();
	string partialFileName = filename+".filepart";
	rename(partialFileName.c_str(), filename.c_str());
}

void FileReceiver::cancelled()
{
	onClose();
	string partialFileName = filename+".filepart";
	unlink(partialFileName.c_str());
}

void FileReceiver::reportError(string message)
{
	RPCParams putFailedParams;
		putFailedParams.set("id", id);
		putFailedParams.set("message", message);
	source->call("putfailed", &putFailedParams);
}

//////////////////////////////////////////////////////////////////////////////

map<int, FileReceiver*> fileReceivers;

RPC_HANDLER(put)
{
	int id = params->getInt("id");
	fileReceivers[id] = new FileReceiver(host, params);
}

RPC_HANDLER(putfinished)
{
	int id = params->getInt("id");
	fileReceivers[id]->finished();
}

RPC_HANDLER(putcancel)
{
	int id = params->getInt("id");
	fileReceivers[id]->cancelled();
}

